#pragma once

#include<iostream>
#include<string>
#include<sstream>
#include<vector>
#include<unordered_map>
#include<fstream>

// GET / HTTP/1.1
// Host: 121.37.190.175:8080
// Connection: keep-alive
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Linux; Android 14; V2154A Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.103 Mobile Safari/537.36 XWEB/1300333 MMWEBSDK/20240501 MMWEBID/6665 MicroMessenger/8.0.50.2701(0x2800325B) WeChat/arm64 Weixin NetType/5G Language/zh_CN ABI/arm64
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/wxpic,image/tpg,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
// X-Requested-With: com.tencent.mm
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

const std::string SEP="\r\n";
const std::string LINE_SEP=" ";
const std::string BLOCK_LINE=SEP;
const std::string HEADER_SEP=": ";
const std::string default_path="wwwroot";
const std::string default_version="HTTP/1.0";       //默认协议版本
const std::string page_404="wwwroot/404.html";      //404
const std::string first_page="index.html";          //首页

bool PraseOneLine(std::string& httprequest,std::string* out_line,const std::string& sep){
    auto pos=httprequest.find(sep);
    if(pos==std::string::npos){
        return false;
    }
    *out_line=httprequest.substr(0,pos);
    httprequest.erase(0,pos+sep.size());
    return true;
}

bool SpritString(const std::string& header,const std::string& sep,std::string* key,std::string* value){
    auto pos=header.find(sep);
    if(pos==std::string::npos){
        return false;
    }
    *key=header.substr(0,pos);
    *value=header.substr(pos+sep.size());
    return true;
}

class HttpRequest{
private:
    bool PraseRequestHeader(std::string& request){
        std::string line;
        while(true){
            bool r=PraseOneLine(request,&line,SEP);
            if(r&&!line.empty()){
                _req_header.push_back(line);
            }
            else if(r&&line.empty()){
                _block_line=BLOCK_LINE;
                return true;
            }
            else {
                return false;
            }
        }
    }
    void PraseRequestLine(){                        // GET / HTTP/1.1
        std::stringstream ss(_req_line);
        ss>>_mothod;
        ss>>_uri;
        ss>>_version;
        _uri=default_path+_uri;
    }

    void PraseRequestHeaderKV(){                    // Host: 121.37.190.175:8080
            for(auto &e:_req_header){
                std::string key;
                std::string value;
                SpritString(e,HEADER_SEP,&key,&value);
                _headerkv.insert(std::make_pair(key,value));
            }
    }  
public:
    HttpRequest(){}
    ~HttpRequest(){}

    std::string GetContend(){                       //获取uri对应的资源
        std::ifstream in;
        std::string content;
        in.open(_uri,std::ios_base::binary);
        if(!in.is_open()) return std::string();

        in.seekg(0,in.end);
        size_t filesize=in.tellg();
        content.resize(filesize);
        in.seekg(0,in.beg);
        in.read((char*)content.c_str(),filesize);

        in.close();
        return content;

        // std::cout<<_uri<<std::endl;
        // std::string contend;
        // std::ifstream in;
        // in.open(_uri);
        // if(in.is_open()){
        //     std::string line;
        //     while(std::getline(in,line)){
        //         contend+=line;
        //     }
        // }
        // in.close();
        // return contend;
    }

    bool prase(std::string& request){               //解析http请求
        if(PraseOneLine(request,&_req_line,SEP)){   //解析http请求行
            PraseRequestLine();                     //解析请求行
            PraseRequestHeader(request);            //解析报头
            PraseRequestHeaderKV();            //解析报头的key-value关系
            return true;
        }
        return false;
    }

    void print(){
        std::cout<<_mothod<<std::endl;
        std::cout<<_uri<<std::endl;
        std::cout<<_version<<std::endl;

        for(auto& e:_headerkv){
            std::cout<<e.first<<"["<<e.second<<"]"<<std::endl;
        }
    }

    std::string suffix(){
        std::string suf;
        
        auto pos=_uri.rfind('.');
        if(pos==std::string::npos) return suf;
        suf=_uri.substr(pos);
        
        
        return suf;
    }

    void seturi(std::string uri)    {_uri=uri;}
    std::string uri()   {return _uri;}
private:
    std::string _req_line;                  //请求行
    std::vector<std::string> _req_header;   //请求报头
    std::string _block_line;                //空行
    std::string _body;                      //相应正文

    std::string _mothod;                    //请求方法
    std::string _uri;                       //uri
    std::string _version;                   //协议版本
    std::unordered_map<std::string,std::string> _headerkv;  //请求报头的key-value
};

class HttpRespond{
private:
    void GetStatusDescribe(int code){
        switch(code){
            case 200:
            _status_desp="OK";
            break;
            case 404:
            _status_desp="Not Found";
        }
    }
    void CreateHeader(){
        if(_headerkv.empty()){return;}
        for(auto &e:_headerkv){
            std::string line=e.first+HEADER_SEP+e.second+SEP;
            _resp_header.push_back(line);
        }
    }

private:
    std::string suf2desc(std::string suf){
        if(suf==".png"){
            return std::string("image/png");
        }
        else if(suf==".html"){
            return std::string("text/html");
        }
        return std::string("text/html");
    }
public:
    HttpRespond(){}
    ~HttpRespond(){}

    void SetHeaderKV(std::string key,std::string value){
        _headerkv[key]=value;
    }

    void bulid(HttpRequest& req){           //构建http响应
        std::string uri=req.uri();          
        if(uri.back()=='/'){
            uri+=first_page;
            req.seturi(uri);
        }
        _version=default_version;           //构建版本号
        _content=req.GetContend();          //获取正文内容
        if(_content.empty()){               //构建错误码
            _status_code=404;
            req.seturi(page_404);
            _content=req.GetContend();      //获取404页面
        }
        else{
            _status_code=200;
        }
        GetStatusDescribe(_status_code);    //构建错误描述
        std::string suf=req.suffix();
        std::string mine=suf2desc(suf);
        SetHeaderKV("Content-Type",mine);
        SetHeaderKV("Content-Length",std::to_string(_content.size()));      
    }

    void serialization(std::string* out_str){
        _resp_line=_version+LINE_SEP+std::to_string(_status_code)+LINE_SEP+_status_desp+SEP;
        _block_line=BLOCK_LINE;
        _body=_content;
        CreateHeader();
        *out_str+=_resp_line;
        for(auto&e:_resp_header){
            *out_str+=e;
        }
        *out_str+=_block_line;
        *out_str+=_body;
    }//序列化

private:
    std::string _resp_line;                 //响应行
    std::vector<std::string> _resp_header;  //响应正文
    std::string _block_line;                //空行
    std::string _body;                      //响应正文

    std::string _version;                   //协议版本
    int _status_code;                       //状态码
    std::string _status_desp;               //状态描述
    std::unordered_map<std::string,std::string> _headerkv;  //相应的键值对
    std::string _content;                   //响应正文
};

bool execute(std::string& in_buffer,std::string&out_buffer){
        HttpRequest req;
        req.prase(in_buffer);
        HttpRespond resp;
        resp.bulid(req);
        resp.serialization(&out_buffer);
        return true;
}